﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

using SmartProject.Exceptions;

namespace SmartProject.BusinessRules
{
    public class FirstInitialAndLastNameUserName : BusinessRule
    {
        public override string Name
        {
            get { return "First initial, last name username"; }
        }

        public override string Description
        {
            get
            {
                return "Username is first initial of first name and concatenated last names";
            }
        }

        /// <summary>
        /// Returns true if the first name or last name has changed.
        /// </summary>
        /// <param name="data">Entity instance containing the previous and new values for comparison.</param>
        /// <returns>True if the first name AND/OR last name has changed.</returns>
        private bool IsChanged(Entity data)
        {
            string previousFirstNameInitial = ((string)data.GetBusinessRuleParameterValue("FirstName")).Substring(0, 1).ToLower();
            string previousLastName = ((string)data.GetBusinessRuleParameterValue("LastName")).ToLower();
            string newFirstNameInitial = ((string)data.GetAttributeValue("FirstName")).Substring(0, 1).ToLower();
            string newLastName = ((string)data.GetAttributeValue("LastName")).ToLower();
            // Has either the first name or last name changed?
            if (previousFirstNameInitial != newFirstNameInitial ||
                previousLastName != newLastName)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// Gets a username based on your first name/last name. Note that
        /// the username is converted to be in lowercase.
        /// </summary>
        /// <param name="data">Entity instance to evaluate.</param>
        /// <returns>Username.</returns>
        private string GetNewUserName(Entity data)
        {
            string firstName = (string)data.GetAttributeValue("FirstName");
            string lastName = (string)data.GetAttributeValue("LastName");
            string userName = firstName.Substring(0, 1) + lastName;

            // Check to see if username has been used. If so, add an initial number
            // to the end.
            MembershipUserCollection users = Membership.FindUsersByName(userName);
            if (users.Count > 0)
            {
                userName += users.Count.ToString();
            }
            return userName.ToLower();
        }

        public override void Implement(Entity data)
        {
            if (data.StoredProc == "smartProject_AddUser")
            {
                string newUserName = GetNewUserName(data);
                data.SetAttribute("UserName", newUserName);
            }
            else if (data.StoredProc == "smartProject_UpdateUser")
            {
                // Has either the first name or last name changed?
                if (IsChanged(data))
                {
                    string userName = (string)data.GetBusinessRuleParameterValue("UserName");
                    MembershipUser previousUser = Membership.GetUser(userName);
                    if (previousUser.IsOnline)
                    {
                        throw new Exceptions.BusinessRuleViolation(String.Format("{0} is currently logged in. Unable to remove user at this time.", userName));
                    }

                    string password = (string)data.GetBusinessRuleParameterValue("Password");
                    if (String.IsNullOrEmpty(password))
                    {
                        // Explain to the user that whenever the username has changed, password
                        // becomes a required field.
                        throw new Exceptions.BusinessRuleViolation("As your username has changed, password is a required field per the selected business rule.");
                    }

                    // We are going to need a new user name. This requires us
                    // to retire the old one and make use of the new username.
                    string newUserName = GetNewUserName(data);
                    string previousUserName = (string)data.GetBusinessRuleParameterValue("UserName");
                    // First remove the old user.
                    string[] roles = Roles.GetRolesForUser(previousUserName);
                    Membership.DeleteUser(previousUserName, true);

                    // Then, add the new user.
                    Membership.CreateUser(newUserName,
                        (string)data.GetBusinessRuleParameterValue("Password"),
                        (string)data.GetAttributeValue("EMail"));
                    Roles.AddUserToRoles(newUserName, roles);
                }
                else
                {
                    string password = (string)data.GetBusinessRuleParameterValue("Password");
                    if (!String.IsNullOrEmpty(password))
                    {
                        BusinessObjects.User user = (BusinessObjects.User)data;
                        string userName = (string)data.GetAttributeValue("UserName");
                        MembershipUser member = Membership.GetUser(userName);
                        string oldPasword = member.ResetPassword();
                        member.ChangePassword(oldPasword, password);
                    }
                }
            }
        }

        public override bool QueryBooleanProperty(string propertyName)
        {
            switch (propertyName)
            {
                case "IsEnableUserNameTextBox":
                    return false;
            }
            throw new MissingPropertyName(String.Format("Property name is missing: {0}", propertyName));
        }
    }
}
